﻿/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#pragma once

#include <string>
#include <vector>
#include <functional>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <chrono>

#ifdef _WIN32
#define ExportSymbol  __declspec(dllexport)
#else
#define ExportSymbol
#endif

#ifdef _WIN32
    #include <windows.h>
	#pragma comment(lib, "kernel32.lib")
#else
    #include <termios.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/select.h>
    #include <sys/ioctl.h>
#endif

namespace NahidaProject {
	class ExportSymbol SerialPort {
	public:
		// 波特率枚举
		enum class ExportSymbol BaudRate {
			BAUDRATE_110 = 110,
			BAUDRATE_300 = 300,
			BAUDRATE_600 = 600,
			BAUDRATE_1200 = 1200,
			BAUDRATE_2400 = 2400,
			BAUDRATE_4800 = 4800,
			BAUDRATE_9600 = 9600,
			BAUDRATE_14400 = 14400,
			BAUDRATE_19200 = 19200,
			BAUDRATE_38400 = 38400,
			BAUDRATE_57600 = 57600,
			BAUDRATE_115200 = 115200,
			BAUDRATE_230400 = 230400,
			BAUDRATE_460800 = 460800,
			BAUDRATE_921600 = 921600
		};

		// 数据位枚举
		enum class ExportSymbol DataBits {
			DATA_5 = 5,
			DATA_6 = 6,
			DATA_7 = 7,
			DATA_8 = 8
		};

		// 停止位枚举
		enum class ExportSymbol StopBits {
			STOP_1 = 1,      // 1个停止位
			STOP_1_5 = 15,   // 1.5个停止位
			STOP_2 = 2       // 2个停止位
		};

		// 校验位枚举
		enum class ExportSymbol Parity {
			NONE,    // 无校验
			ODD,     // 奇校验
			EVEN,    // 偶校验
			MARK,    // 标记校验
			SPACE    // 空格校验
		};

		// 流控制枚举
		enum class ExportSymbol FlowControl {
			NONE,           // 无流控制
			HARDWARE,       // 硬件流控制
			SOFTWARE        // 软件流控制
		};

		// 错误码枚举
		enum class ExportSymbol ErrorCode {
			SUCCESS = 0,
			INVALID_PARAMETER,
			PORT_NOT_OPEN,
			PORT_ALREADY_OPEN,
			OPEN_FAILED,
			CONFIGURE_FAILED,
			WRITE_FAILED,
			READ_FAILED,
			TIMEOUT,
			UNKNOWN_ERROR
		};

		// 回调函数类型
		using DataReceivedCallback = std::function<void(const std::vector<uint8_t>& data)>;
		using ErrorCallback = std::function<void(ErrorCode error)>;

	public:
		SerialPort();
		~SerialPort();
		SerialPort(const SerialPort&) = delete;
		SerialPort& operator=(const SerialPort&) = delete;
		ErrorCode OpenSerialPort(const std::string& portName);
		void CloseSerialPort();
		bool SerialPortIsOpen() const;
		ErrorCode Configure(BaudRate baudRate = BaudRate::BAUDRATE_9600, DataBits dataBits = DataBits::DATA_8, StopBits stopBits = StopBits::STOP_1, Parity parity = Parity::NONE, FlowControl flowControl = FlowControl::NONE);
		ErrorCode Write(const std::vector<uint8_t>& data);
		ErrorCode WriteString(const std::string& data);
		ErrorCode Write(const uint8_t* data, size_t length);
		ErrorCode Read(std::vector<uint8_t>& data, size_t maxBytes, int timeoutMs = -1, size_t* bytesRead = nullptr);
		ErrorCode ReadExact(std::vector<uint8_t>& data, size_t bytesToRead, int timeoutMs = -1);
		void SetDataReceivedCallback(const DataReceivedCallback& callback);
		void SetErrorCallback(const ErrorCallback& callback);

		ErrorCode StartAsyncRead();
		void StopAsyncRead();

		ErrorCode FlushInput();
		ErrorCode FlushOutput();
		ErrorCode Flush();

		bool GetClearToSend();   // Clear To Send
		bool GetDataSetReady();   // Data Set Ready
		bool GetRingIndicator();    // Ring Indicator
		bool GetCarrierDetect();    // Carrier Detect

		// 设置串口控制信号
		ErrorCode SetRequestToSend(bool enable);  // Request To Send
		ErrorCode SetDataTerminalReady(bool enable);  // Data Terminal Ready

		// 获取错误描述
		static std::string GetErrorString(ErrorCode error);

	private:
		// 平台相关实现
#ifdef _WIN32
		HANDLE handle_;
		OVERLAPPED overlapped_;
#else
		int fd_;
#endif

		std::string portName_;
		std::atomic<bool> isOpen_;
		std::atomic<bool> isAsyncReading_;

		// 配置参数
		BaudRate baudRate_;
		DataBits dataBits_;
		StopBits stopBits_;
		Parity parity_;
		FlowControl flowControl_;

		// 回调函数
		DataReceivedCallback dataReceivedCallback_;
		ErrorCallback errorCallback_;

		// 异步读取线程
		std::thread asyncReadThread_;
		std::mutex callbackMutex_;

		// 内部方法
		ErrorCode ConfigureSerialPort();
		void AsyncReadLoop();
		//ErrorCode WaitForData(int timeoutMs);
	};
}
